/*
 * @Description:baseSet
 * @Version: 2.0
 * @Autor: zss
 * @Date: 2024-05-10 16:21:40
 * @LastEditors: swc
 * @LastEditTime: 2024-08-31 14:53:18
 */
import { Tsrv, ifs, ts } from '@/services';
import { N_BaseSet } from './types';

interface arrayToObj {
  field1?: string | undefined;
  field2?: string | undefined;
  field3?: string | undefined;
  field4?: string | undefined;
}

class T_cmd {
  // 主组件箱
  private compBox: ifs.I_compBox;

  // 主组件ID
  private compID: string;

  // 主组件实例
  private self: N_BaseSet.BaseSet;
  // 主组refs

  // 过滤条件
  private filter: any = {};

  // 更新记录
  private UpdateRecords: any[] = [];

  // 新增记录
  private InsertRecords: any[] = [];

  public baseSetFunName: string = Tsrv.globalVar.funName.SYS_BASE_SET;

  public baseSetDataMd5: string = '';

  public oldDaseSetData: { [key: string]: any } = {};

  // 主组件created里初始化
  public init(self: any, compBoxInfo: ifs.I_compBoxInfo) {
    this.self = self;
    this.compBox = compBoxInfo.TcompBox;
    this.compID = compBoxInfo.compID;
  }

  public setFilter(e: any) {
    this.filter = e;
  }

  public async loadData() {
    this.InsertRecords = [];
    this.UpdateRecords = [];
    const [b, res, rows, err] = await this.doLoadData(
      this.baseSetFunName,
      this.baseSetFunName,
      Tsrv.globalVar.dbType.MYSQL
    );
    if (b) {
      const loadData = {};
      const obj = {};
      for (const el of rows) {
        if (el.data_type !== 'JSON') {
          this.self.formHint[el.f_key] = el.f_comment;
          obj[el.f_key] = el.f_value_a;
        } else {
          if (el.f_key === 'SYS_STYLE_TEMPLATE') {
            loadData[el.f_key] = JSON.parse(el.f_value_a);
            continue;
          }
          const value = JSON.parse(el.f_value_a);
          if (typeof value[0] === 'string') {
            const arr: Array<arrayToObj> = [];
            this.arrToObj(value, arr);
            loadData[el.f_key] = arr;
          } else {
            loadData[el.f_key] = value;
          }
        }
      }
      if (!Tsrv.utils.noValue(obj)) {
        loadData['set1'] = obj;
        this.self.formCustom = obj;
      }
      this.self.baseSetData = loadData;
      const data = Tsrv.utils.clone(loadData, true);
      this.oldDaseSetData = data;
      this.baseSetDataMd5 = Tsrv.utils.md5(JSON.stringify(this.oldDaseSetData));
    } else {
      this.self.$msg(err ?? res.msg);
    }
  }

  // 加载时如果是数组进行转换，[xxx, xxx]转换为{field1：xxx, field2: xxx,...}
  private arrToObj(data: Array<string>, b?: Array<arrayToObj>) {
    const obj: arrayToObj = {};
    if (data.length === 0) {
      return;
    }
    if (data.length < 4) {
      const count = data.length;
      // shift会改变原数组的长度，所以在循环之前存储data的长度
      for (let index = 0; index < count; index++) {
        obj[`field${index + 1}`] = data.shift();
      }
      b.push(obj);
      return;
    }
    for (let index = 0; index < 4; index++) {
      obj[`field${index + 1}`] = data.shift();
    }
    b.push(obj);
    this.arrToObj(data, b);
  }

  public doLoadData(funName: string, tableName: string, dbType: string) {
    const gpd = new ts.T_getPartDataArg();
    gpd.setFilter(this.filter);
    gpd.setFunName(tableName);
    gpd.setTableName(tableName);
    gpd.setDbType(dbType);
    gpd.setLang(this.self.$i18n.locale);
    gpd.setPage(1, 99999);
    gpd.setRule({} as ifs.I_rule);

    return Tsrv.getData(gpd);
  }

  // 整理更新数据
  private OrganizeUpdateData(data) {
    data.forEach(el => {
      const obj = {};
      obj['f_key'] = el.field;
      obj['changes'] = [];
      obj['changes'].push({ field: 'f_value_a', value: el.value });
      this.UpdateRecords.push(obj);
    });
  }

  // 保存
  public handleSave(data: Array<{ field: string; value: any }>) {
    // 保存前操作
    this.OrganizeUpdateData(data);
    this.saveCTD().then(e => {
      // 保存成功后
      this.loadData();
    });
  }

  /**
   * @description: 新旧数据对比
   * @param {object} oldData
   * @param {object} newData
   * @return {*}
   * @author: zss
   * @Date: 2024-05-24 10:09:09
   * @LastEditors: zss
   * @LastEditTime: Do not edit
   */
  public findDifferences(
    oldData: { [key: string]: string },
    newData: { [key: string]: string }
  ): Array<{ field: string; value: any }> {
    const differences = [];

    // 遍历obj1的键
    for (const key in newData) {
      if (Object.prototype.hasOwnProperty.call(newData, key)) {
        // 如果obj1的键在obj2中不存在或值不同
        if (
          !Object.prototype.hasOwnProperty.call(oldData, key) ||
          oldData[key] !== newData[key]
        ) {
          differences.push({ field: key, value: newData[key] });
        }
      }
    }
    return differences;
    // return !Tsrv.utils.noValue(this.UpdateRecords);
  }

  private saveCTD() {
    return new Promise((resolve, reject) => {
      const ctd = new ts.T_ctdArg();
      ctd
        .setTableName(this.baseSetFunName)
        .setDbType(Tsrv.globalVar.dbType.MYSQL)
        .setRule({} as ifs.I_rule);
      if (!Tsrv.utils.noValue(this.InsertRecords)) {
        const scope = {};
        const bDatas: ifs.I_baseData[] = [];
        this.InsertRecords.forEach(item => {
          delete item['isCreated'];
          const rowData = [];
          for (const key in item) {
            const obj = {};
            obj['field'] = key;
            obj['value'] = item[key];
            rowData.push(obj);
          }

          const bData = new ts.T_baseData();
          bData
            .setDataRule({} as ifs.I_rule)
            .setFileInfo({})
            .setRowData(...(rowData as ifs.I_fv[]));
          bDatas.push(bData);
        });
        ctd.setInsRecDataMany(scope, ...bDatas);
      }
      if (!Tsrv.utils.noValue(this.UpdateRecords)) {
        let filter: any = {};
        const ctdUpdDatas: ifs.I_ctdUpdData[] = [];
        this.UpdateRecords.forEach(item => {
          const ctdUpdData = new ts.T_ctdUpdData();
          ctdUpdData.setDataRule({} as ifs.I_rule).setFileInfo({});
          filter = { f_key: item.f_key };
          ctdUpdData.setFilter(filter);
          ctdUpdData.setRowData(...item.changes);
          ctdUpdDatas.push(ctdUpdData);
        });
        ctd.setUpdRecDataMany(...ctdUpdDatas);
      }
      if (
        !Tsrv.utils.noValue(ctd.insertRecords) ||
        !Tsrv.utils.noValue(ctd.updateRecords)
      ) {
        Tsrv.batRows(ctd).then(resp => {
          const [b, res, msg] = resp;
          msg && this.self.$msg(msg);
          if (b) {
            resolve(true);
          } else {
            reject();
          }
        });
      }
    });
  }
}
interface I_cmd extends T_cmd {}
export { I_cmd, T_cmd };
